package top.ljjapp.soufang.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import top.ljjapp.soufang.security.AuthFilter;
import top.ljjapp.soufang.security.AuthProvider;
import top.ljjapp.soufang.security.LoginAuthFailHandler;
import top.ljjapp.soufang.security.LoginUrlEntryPoint;

@EnableWebSecurity //使用webSecurity
@EnableGlobalMethodSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     * HTTP权限控制 配置
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilterBefore(authFilter(), UsernamePasswordAuthenticationFilter.class);
        //资源访问权限(访问这些路径都会根据相应规则被拦截)
        http.authorizeRequests()
                .antMatchers("/admin/login").permitAll() //管理员登录
                .antMatchers("/static/**").permitAll() //静态资源
                .antMatchers("/user/login").permitAll() //用户登录
                .antMatchers("/admin/**").hasRole("ADMIN")
                .antMatchers("/user/**").hasAnyRole("ADMIN","USER")
                .antMatchers("/api/user/**").hasAnyRole("ADMIN","USER")
        .and()
                //被拦截后登录
                .formLogin()
                .loginProcessingUrl("/login") //配置角色登录处理入口
                .failureHandler(loginAuthFailHandler()) //登录失败处理
        .and()
                .logout() //登出
                .logoutUrl("/logout") //配置角色登出处理入口
                .logoutSuccessUrl("/logout/page") //成功登出页面
                .deleteCookies("JESSIONID")
                .invalidateHttpSession(true)
        .and()
                //自定义登录
                //配置基于角色的登录入口控制器
                .exceptionHandling()
                .authenticationEntryPoint(urlEntityPoint())
                .accessDeniedPage("/403")
        .and()
        ;
        http.csrf().disable(); //关闭防御策略
        http.headers().frameOptions().sameOrigin();
    }

    /**
     * 自定义策略（验证用户名密码）
     * @param auth
     * @throws Exception
     */
    @Autowired
    public void configGlobal(AuthenticationManagerBuilder auth) throws  Exception{
//        auth.inMemoryAuthentication().withUser("admin")
//                .password("admin").roles("ADMIN").and();
        auth.authenticationProvider(authProvider()).eraseCredentials(true);
    }

    /**
     * 自定义认证实现
     * @return
     */
    @Bean
    public AuthProvider authProvider(){
        return new AuthProvider();
    }


    /**
     * 基于角色的登录入口控制器
     * @return
     */
    @Bean
    public LoginUrlEntryPoint urlEntityPoint(){
        return new LoginUrlEntryPoint("/user/login");
    }

    /**
     * 登录验证失败处理器
     * @return
     */
    @Bean
    public LoginAuthFailHandler loginAuthFailHandler(){
        return new LoginAuthFailHandler(urlEntityPoint());
    }

    @Bean
    public AuthenticationManager authenticationManager() {
        AuthenticationManager authenticationManager = null;
        try {
            authenticationManager =  super.authenticationManager();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return authenticationManager;
    }

    @Bean
    public AuthFilter authFilter(){
        AuthFilter authFilter = new AuthFilter();
        authFilter.setAuthenticationManager(authenticationManager());
        authFilter.setAuthenticationFailureHandler(loginAuthFailHandler());
        return authFilter;
    }
}
